

import sys, importlib, bpy

def reset_addon():
    import addon_utils
    try: addon_utils.disable("ossl")
    except: pass
    importlib.invalidate_caches()
    for mod in filter(lambda n: n.startswith("ossl"), sys.modules.copy()): sys.modules.pop(mod)
    addon_utils.enable("ossl")
    print("reloading in util: ossl")
    import ossl
    print("reloaded in util: ossl")

def imports(parent_module_name, sub_module_name):
    mod = '{}.{}'.format(parent_module_name, sub_module_name)
    print("imports: " + mod)
    if mod in sys.modules: importlib.reload(sys.modules[mod])
    else: globals()[mod] = importlib.import_module(mod)
    mod = sys.modules[mod]
    if mod and hasattr(mod, "register"): mod.register()

def release(parent_module_name, sub_module_name):
    mod = '{}.{}'.format(parent_module_name, sub_module_name)
    print("release: " + mod)
    if (mod in sys.modules):
        mod = sys.modules[mod]
        if hasattr(mod, "unregister"): mod.unregister()
        globals().pop(mod.__name__, None)
        sys.modules.pop(mod.__name__, None)

def fmt(v):
    if type(v) is str: return "'" + v + "'"
    if type(v).__name__ == "Euler": return "(" + fmt(tuple((v.x,v.y,v.z))) + ",'" + v.order + "')"
    if hasattr(v, "__getitem__"): return "(" + ",".join(fmt(x) for x in tuple(v)) + ")"
    if not hasattr(v, "__round__"): return str(v)
    v = str(round(v, 4))
    while len(v) > 0 and v[-1] == "0": v = v[:-1]
    if len(v) == 0: v = "0"
    if v[-1] == ".": v = v[:-1]
    if v == "-0": v = "0"
    return v

def test_util(s):
    print("\n" + s + "\n")

def setMode(mode):
    if (bpy.context.mode != mode):
        bpy.ops.object.mode_set(mode=mode)


def path(s):
    return __file__[0:__file__.index("\\util\\")] + "\\" + s

def datapath(s):
    import bpy
    return bpy.utils.user_resource("DATAFILES") + "\\addons\\ossl\\" + s

def addon_url():
    import os, ossl
    url = os.path.dirname(ossl.bl_info.get("doc_url")) + "/ossl/"
    return url


import os, stat

def fs_info(fn):
    import ossl.util as util 
    from datetime import datetime as dt
    st = os.stat(fn)
    mode = "d" if stat.S_ISDIR(st.st_mode) else "f"
    dt = util.format_utc(dt.fromtimestamp(st.st_mtime))
    return (mode, fn, dt)

def fs_info_str(fn):
    info = fs_info(fn)
    return info[0] + info[1] + "\x01" + info[2]

def fs_dirlist(dn):
    if dn is not None:
        old_dn = os.getcwd()
        os.chdir(dn)
    ll = [fs_info_str(n) for n in os.listdir()]
    if dn is not None:
        os.chdir(old_dn)
    ll.sort()
    def spl(s):
        s = s.split("\x01")
        return (s[0][0:1], s[0][1:], s[1])
    return list(spl(n) for n in ll)

def fs_xml_(indent, i):
    import os, stat
    import ossl.util as util
    s = []
    if i[0] == "d":
        s.append("\t"*indent + "<d n='" + i[1] + "' t='" + i[2] + "'>\n")
        os.chdir(i[1])
        for ii in util.fs_dirlist(None): s.append(fs_xml_(indent+1, ii))
        os.chdir("..")
        s.append("\t"*indent + "</d>\n")
    else:
        s.append("\t"*indent + "<f n='" + i[1] + "' t='" + i[2] + "'/>\n")
    return "".join(s)

def fs_xml(subdirname):
    return fs_xml_(0, fs_info(subdirname))


def verify_dir(dn, dnx):
    try: os.mkdir(dn)
    except: pass
    for x in dnx.split("/"):
        dn += "\\" + x
        try: os.mkdir(dn)
        except: pass
    try: shutil.rmtree(dn)
    except: pass
    try: os.mkdir(dn)
    except: pass
    return dn


def parse_utc(s):
    from datetime import datetime
    return datetime.fromisoformat(s)

def format_utc(t):
    from datetime import datetime
    return t.astimezone().isoformat()


def sig(fn):
    from inspect import signature as sig
    return sig(fn)


def register():
    sys.modules["ossl.util"].__slots__ = 'imports', 'release'

    print("registering: OSSL Utilities")
    #bpy.utils.register_class(OSSL_Preferences)
    print("registered: OSSL Utilities")

def unregister():
    print("unregistering: OSSL Utilities")
    #bpy.utils.unregister_class(OSSL_Preferences)
    print("unregistered: OSSL Utilities")

if __name__ == "__main__":
    print("\n\n")
    reset_addon()
